#include "csphere.h"
#include <QDebug>
#include <GL/glu.h>

CSphere::CSphere()
{
    this->m_pBB = NULL;
    this->m_pBS = NULL;
}

CSphere::CSphere(CPoint3f position, float r, CMaterial mat)
{
    this->m_Position = position;
    this->m_fRadius = r;
    this->m_Material = mat;
    this->m_pBS = NULL;
    this->setupBoundingBox();
}

CSphere::~CSphere()
{
    delete this->m_pBB;
}

void CSphere::paint()
{
    glColor3f(this->m_Material.m_fRed, this->m_Material.m_fGreen, this->m_Material.m_fBlue);
    glPushMatrix();
        glTranslatef(this->m_Position.GetX(), this->m_Position.GetY(), this->m_Position.GetZ());
        GLUquadric *quadric;
        quadric = gluNewQuadric();
        gluQuadricDrawStyle(quadric, GLU_FILL);
        gluQuadricNormals(quadric, GLU_SMOOTH);
        /* If we ever changed/used the texture or orientation state
        of quadObj, we'd need to change it to the defaults here
        with gluQuadricTexture and/or gluQuadricOrientation. */
        gluSphere(quadric, this->m_fRadius, 32, 32);
    glPopMatrix();
}

bool CSphere::intersect(CRay * pRay, CPoint3f & P, CVector3f & V)
{
    if (this->m_pBB)
        if (!this->m_pBB->intersect(pRay))
            return false;

    CVector3f oToPos(this->m_Position - pRay->m_Start);
    float tca = oToPos*pRay->m_Direction;

    if (tca < 0.0)
        return false;

    float d2 = oToPos.length2() - pow(tca,2.0);
    float r2 = pow(this->m_fRadius, 2.0);

    if (d2 < 0.0 || d2 > r2)
        return false;

    float thc = sqrt(r2 - d2);

    float t = tca - thc;

    P = pRay->m_Start + pRay->m_Direction*t;

    V = P - this->m_Position;

    return true;
}


std::string CSphere::className()
{
    std::string str("CSphere");
    return str;
}

void CSphere::setupBoundingBox()
{
    if (this->m_pBB)
        delete this->m_pBB;
    this->m_pBB = new CBoundingBox(this,CPoint3f(this->m_Position.GetX()-this->m_fRadius,
                                                 this->m_Position.GetY()-this->m_fRadius,
                                                 this->m_Position.GetZ()-this->m_fRadius),
                                        CPoint3f(this->m_Position.GetX()+this->m_fRadius,
                                                 this->m_Position.GetY()+this->m_fRadius,
                                                 this->m_Position.GetZ()+this->m_fRadius));
}

void CSphere::setupBoundingSphere()
{
    this->m_pBS = NULL;
}
